package tech.mhuang.ext.interchan.autoconfiguration.datasecure.util;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 加密解密工具类
 *
 * @author mhuang
 * @since 1.6.2
 */
public class CryptoUtil {

    public final static String AES = "AES";
    public final static String DES = "DES";

    /**
     * 加密
     *
     * @param content      加密的原文
     * @param pwd          密匙
     * @param instanceName 加密实例名
     * @param coding       编码
     * @return 加密后结果Str
     * @throws Exception 异常
     */
    public static String encrypt(String content, String pwd, String instanceName, Charset coding) throws Exception {
        return crypt(content, pwd, instanceName, coding, Cipher.ENCRYPT_MODE);
    }

    /**
     * 解密
     *
     * @param content      密文
     * @param pwd          密匙
     * @param instanceName 解密实例名
     * @param coding       编码
     * @return 解码后的原文
     * @throws Exception 异常
     */
    public static String decrypt(String content, String pwd, String instanceName, Charset coding) throws Exception {
        return crypt(content, pwd, instanceName, coding, Cipher.DECRYPT_MODE);
    }

    /**
     * 密码处理
     *
     * @param content      处理的内容
     * @param pwd          处理的内容的密匙
     * @param instanceName 实例名
     * @param coding       编码
     * @param type         加密 or 解密
     * @return 密码结果
     * @throws Exception 异常
     */
    private static String crypt(String content, String pwd, String instanceName, Charset coding, int type) throws Exception {
        KeyGenerator generator = KeyGenerator.getInstance(instanceName);
        SecureRandom random = new SecureRandom();
        random.setSeed(pwd.getBytes());
        generator.init(random);
        SecretKey secretKey = generator.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec key = new SecretKeySpec(enCodeFormat, instanceName);
        Cipher cipher = Cipher.getInstance(instanceName);
        cipher.init(type, key);
        if (type == Cipher.ENCRYPT_MODE) {
            byte[] byteContent = content.getBytes(coding);
            return Base64.getEncoder().encodeToString(cipher.doFinal(byteContent));
        } else {
            byte[] byteContent = Base64.getDecoder().decode(content);
            return new String(cipher.doFinal(byteContent), coding);
        }
    }
}
